package org.com.lcuiot.service;


import io.mybatis.mapper.example.Example;
import org.com.lcuiot.common.LcuConst;
import org.com.lcuiot.common.TimeUtil;
import org.com.lcuiot.database.dto.Result;
import org.com.lcuiot.database.entity.*;
import org.com.lcuiot.database.mapper.AreaMapper;
import org.com.lcuiot.database.mapper.DeviceDataMapper;
import org.com.lcuiot.database.mapper.DeviceStreamMapper;
import org.com.lcuiot.database.mapper.ProductMapper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.stream.Collectors;

/**
 * 设备数据点服务
 *
 * @author gaoge
 * @since 2022/10/27 14:31
 */
@Service
public class DeviceDataService {
    private static final Logger logger = LoggerFactory.getLogger(DeviceDataService.class);
    private final DeviceDataMapper deviceDataMapper;
    private final ProductMapper productMapper;
    private final AreaMapper areaMapper;
    private final DeviceStreamMapper deviceStreamMapper;

    @Autowired
    public DeviceDataService(DeviceDataMapper deviceDataMapper, ProductMapper productMapper, AreaMapper areaMapper, DeviceStreamMapper deviceStreamMapper) {
        this.deviceDataMapper = deviceDataMapper;
        this.productMapper = productMapper;
        this.areaMapper = areaMapper;
        this.deviceStreamMapper = deviceStreamMapper;
    }


    /**
     * 添加设备数据点信息
     *
     * @param deviceData 请求参数
     * @return Result<Object>
     * @author gaoge
     */
    public Result<Object> addDeviceData(DeviceData deviceData) {
        Result<Object> result = Result.build();
        try {
            deviceData.setCreateAt(TimeUtil.currentTimeMillis());
            deviceData.setUpdateAt(TimeUtil.currentTimeMillis());
            Optional<DeviceData> deviceDataModel = selectByDeviceIdAndDataAt(deviceData.getDevId(), deviceData.getDataAt());
            if (!deviceDataModel.isPresent()) {
                deviceDataMapper.insert(deviceData);
            }
            result.setData(deviceData);
        } catch (Exception e) {
            logger.error("添加设备数据点信息发生异常:", e);
            result.setCode(500).setMsg("添加设备数据点信息发生异常");
        }
        return result;
    }

    public Optional<DeviceData> selectByDeviceId(Long id) {
        return deviceDataMapper.selectByPrimaryKey(id);
    }

    public Optional<DeviceData> selectByDeviceIdAndDataAt(String devId, Long dataAt) {
        DeviceData deviceData = new DeviceData();
        deviceData.setDevId(devId);
        deviceData.setDataAt(dataAt);
        return deviceDataMapper.selectOne(deviceData);
    }

    /**
     * 根据设备ID修改设备数据点信息
     *
     * @param s 请求信息
     * @return Result<Object>
     * @author gaoge
     */
    public Result<Object> patchDeviceData(DeviceData s) {
        Result<Object> result = Result.build();
        try {
            Optional<DeviceData> device = selectByDeviceId(s.getId());
            if (device.isPresent()) {
                s.setUpdateAt(TimeUtil.currentTimeMillis());
                deviceDataMapper.updateByPrimaryKeySelective(s);
            }
            result.setData(s);
        } catch (Exception e) {
            logger.error("根据设备ID修改设备数据点信息发生异常:", e);
            result.setCode(500).setMsg("根据设备ID修改设备数据点信息发生异常");
        }
        return result;
    }

    /**
     * 根据区域ID查询数据流最新数据信息
     *
     * @param areaId 区域ID
     * @return Result<Object>
     */
    public Result<Object> queryAllDataStreamInfo(Long areaId, Long organizationId) {
        Result<Object> result = Result.build();
        try {
            Optional<Area> areaOptional = areaMapper.selectByPrimaryKey(areaId);
            if (!areaOptional.isPresent()) {
                return result.setCode(500).setMsg("区域不存在");
            }
            if (!areaOptional.get().getOrganizationId().equals(organizationId)) {
                return result.setCode(500).setMsg("该区域不属于当前机构，无法操作");
            }
            Product product = new Product();
            product.setAreaId(areaId);
            List<Product> products = productMapper.selectList(product);
            if (products.isEmpty()) {
                return result.setCode(500).setMsg("该区域下不存在产品");
            }
            List<String> productIds = products.stream().map(Product::getProductId).filter(Objects::nonNull).collect(Collectors.toList());
            Map<String, String> productIdName = products.stream().collect(Collectors.toMap(Product::getProductId, Product::getProductName));
            Example<DeviceStream> deviceStreamExample = new Example<>();
            Example.Criteria<DeviceStream> criteria = deviceStreamExample.createCriteria();
            criteria.andIn(DeviceStream::getProductId, productIds);
            List<DeviceStream> deviceStreams = deviceStreamMapper.selectByExample(deviceStreamExample);
            List<SensorDataModel> sensorDataModels = new ArrayList<>();
            Map<String, Object> lineChartMap = new HashMap<>();
            for (DeviceStream deviceStream : deviceStreams) {
                DeviceData deviceData = deviceDataMapper.selectRecentByDevIdAndDsId(deviceStream.getDevId(), deviceStream.getName());
                SensorDataModel sensorDataModel = new SensorDataModel();
                sensorDataModel.setDevId(deviceStream.getDevId());
                sensorDataModel.setProductId(deviceStream.getProductId());
                sensorDataModel.setDataStreamName(deviceStream.getName());
                sensorDataModel.setProductName(productIdName.get(deviceStream.getProductId()));
                if (!Objects.isNull(deviceData)) {
                    sensorDataModel.setDataAt(deviceData.getDataAt());
                    sensorDataModel.setDataValue(deviceData.getDataValue());
                }
                sensorDataModels.add(sensorDataModel);
                if (deviceStream.getName().equals(LcuConst.AIR_HUM)) {
                    List<DeviceData> airHumDeviceData = deviceDataMapper.selectRecentThirtyData(deviceStream.getDevId(), deviceStream.getName());
                    lineChartMap.put(LcuConst.AIR_HUM_LINE_CHART, airHumDeviceData);
                }
                if (deviceStream.getName().equals(LcuConst.AIR_TEMP)) {
                    List<DeviceData> airHumDeviceData = deviceDataMapper.selectRecentThirtyData(deviceStream.getDevId(), deviceStream.getName());
                    lineChartMap.put(LcuConst.AIR_TEMP_LINE_CHART, airHumDeviceData);
                }

            }
            Map<String, Object> sensorDataModelMap = sensorDataModels.stream().collect(Collectors.toMap(SensorDataModel::getDataStreamName, n -> n, (k1, k2) -> k2));
            sensorDataModelMap.putAll(lineChartMap);
            result.setData(sensorDataModelMap);
        } catch (Exception e) {
            logger.error("根据区域ID查询所有数据流最新数值发生异常:", e);
            result.setCode(500).setMsg("根据区域ID查询所有数据流最新数值发生异常");
        }
        return result;
    }
}
